home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / HTStyle.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  9KB  |  364 lines

  1. /*    Style Implementation for Hypertext            HTStyle.c
  2. **    ==================================
  3. **
  4. **    Styles allow the translation between a logical property
  5. **    of a piece of text and its physical representation.
  6. **
  7. **    A StyleSheet is a collection of styles, defining the
  8. **    translation necessary to
  9. **    represent a document. It is a linked list of styles.
  10. */
  11. #include "HTStyle.h"
  12. #include "HTUtils.h"
  13.  
  14. /*    Create a new style
  15. */
  16. PUBLIC HTStyle* HTStyleNew NOARGS
  17. {
  18.     HTStyle * self = (HTStyle *)malloc(sizeof(*self));
  19.     memset(self, 0, sizeof(*self));
  20.     self->font = (HTFont) 0;
  21.     self->color = 0;
  22.     return self;
  23. }
  24.  
  25. /*    Create a new style with a name
  26. */
  27. PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
  28. {
  29.     HTStyle * self = HTStyleNew();
  30.     StrAllocCopy(self->name, name);
  31.     return self;
  32. }
  33.  
  34.  
  35. /*    Free a style
  36. */
  37. PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
  38. {
  39.     if (self->name) free(self->name);
  40.     if (self->SGMLTag) free(self->SGMLTag);
  41.     free(self);
  42.     return 0;
  43. }
  44.  
  45.  
  46. #ifdef SUPPRESS  /* Only on the NeXT */
  47. /*    Read a style from a stream    (without its name)
  48. **    --------------------------
  49. **
  50. **    Reads a style with paragraph information from a stream.
  51. **    The style name is not read or written by these routines.
  52. */
  53. #define NONE_STRING "(None)"
  54. #define HTStream NXStream
  55.  
  56. HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
  57. {
  58.     char myTag[STYLE_NAME_LENGTH];
  59.     char fontName[STYLE_NAME_LENGTH];
  60.     NXTextStyle *p;
  61.     int    tab;
  62.     int gotpara;        /* flag: have we got a paragraph definition? */
  63.     
  64.     NXScanf(stream, "%s%s%f%d",
  65.     myTag,
  66.     fontName,
  67.     &style->fontSize,
  68.     &gotpara);
  69.     if (gotpara) {
  70.     if (!style->paragraph) {
  71.         style->paragraph = malloc(sizeof(*(style->paragraph)));
  72.         style->paragraph->tabs = 0;
  73.     }
  74.     p = style->paragraph;
  75.     NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
  76.         &p->indent1st,
  77.         &p->indent2nd,
  78.         &p->lineHt,
  79.         &p->descentLine,
  80.         &p->alignment,
  81.         &style->spaceBefore,
  82.         &style->spaceAfter,
  83.         &p->numTabs);
  84.     if (p->tabs) free(p->tabs);
  85.     p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
  86.     for (tab=0; tab < p->numTabs; tab++) {
  87.         NXScanf(stream, "%hd%f",
  88.             &p->tabs[tab].kind,
  89.             &p->tabs[tab].x);
  90.     }
  91.     } else { /* No paragraph */
  92.         if (style->paragraph) {
  93.             free(style->paragraph);
  94.             style->paragraph = 0;
  95.     }
  96.     } /* if no paragraph */
  97.     StrAllocCopy(style->SGMLTag, myTag);
  98.     if (strcmp(fontName, NONE_STRING)==0)
  99.         style->font = 0;
  100.     else
  101.         style->font = [Font newFont:fontName size:style->fontSize];
  102.     return 0;
  103.  
  104. }
  105.  
  106.  
  107. /*    Write a style to a stream in a compatible way
  108. */
  109. HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
  110. {
  111.     int tab;
  112.     NXTextStyle *p = style->paragraph;
  113.     NXPrintf(stream, "%s %s %f %d\n",
  114.     style->SGMLTag,
  115.     style->font ? [style->font name] : NONE_STRING,
  116.     style->fontSize,
  117.     p!=0);
  118.  
  119.     if (p) {
  120.     NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
  121.         p->indent1st,
  122.         p->indent2nd,
  123.         p->lineHt,
  124.         p->descentLine,
  125.         p->alignment,
  126.         style->spaceBefore,
  127.         style->spaceAfter,
  128.         p->numTabs);
  129.         
  130.     for (tab=0; tab < p->numTabs; tab++)
  131.         NXPrintf(stream, "\t%d %f\n",
  132.             p->tabs[tab].kind,
  133.             p->tabs[tab].x);
  134.     }
  135.     return style;
  136. }
  137.  
  138.  
  139. /*    Write a style to stdout for diagnostics
  140. */
  141. HTStyle * HTStyleDump (HTStyle * style)
  142. {
  143.     int tab;
  144.     NXTextStyle *p = style->paragraph;
  145.     printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
  146.         style,
  147.     style->name,
  148.     style->SGMLTag,
  149.     [style->font name],
  150.     style->fontSize);
  151.     if (p) {
  152.         printf(
  153.         "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
  154.     "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
  155.         p->indent1st,
  156.         p->indent2nd,
  157.         p->lineHt,
  158.         p->descentLine,
  159.         p->alignment,
  160.         p->numTabs,
  161.         style->spaceBefore,
  162.         style->spaceAfter);
  163.         
  164.     for (tab=0; tab < p->numTabs; tab++) {
  165.         printf("\t\tTab kind=%d at %.0f\n",
  166.             p->tabs[tab].kind,
  167.             p->tabs[tab].x);
  168.         }
  169.     printf("\n");
  170.     } /* if paragraph */
  171.     return style;
  172. }
  173. #endif
  174.  
  175.  
  176. /*            StyleSheet Functions
  177. **            ====================
  178. */
  179.  
  180. /*    Searching for styles:
  181. */
  182. HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
  183. {
  184.     HTStyle * scan;
  185.     for (scan=self->styles; scan; scan=scan->next)
  186.         if (0==strcmp(scan->name, name)) return scan;
  187.     if (TRACE) fprintf(stderr, "StyleSheet: No style named `%s'\n", name);
  188.     return 0;
  189. }
  190.  
  191. #ifdef NEXT_SUPRESS        /* Not in general common code */
  192.  
  193. HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
  194. {
  195.     HTStyle * scan;
  196.     for (scan=self->styles; scan; scan=scan->next)
  197.         if (scan->paragraph == para) return scan;
  198.     return 0;
  199. }
  200.  
  201. /*    Find the style which best fits a given run
  202. **    ------------------------------------------
  203. **
  204. **    This heuristic is used for guessing the style for a run of
  205. **    text which has been pasted in. In order, we try:
  206. **
  207. **    A style whose paragraph structure is actually used by the run.
  208. **    A style matching in font
  209. **    A style matching in paragraph style exactly
  210. **    A style matching in paragraph to a degree
  211. */
  212.  
  213. HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
  214. {
  215.     HTStyle * scan;
  216.     HTStyle * best = 0;
  217.     int    bestMatch = 0;
  218.     NXTextStyle * rp = run->paraStyle;
  219.     for (scan=self->styles; scan; scan=scan->next)
  220.         if (scan->paragraph == run->paraStyle) return scan;    /* Exact */
  221.  
  222.     for (scan=self->styles; scan; scan=scan->next){
  223.         NXTextStyle * sp = scan->paragraph;
  224.         if (sp) {
  225.         int match = 0;
  226.         if (sp->indent1st ==    rp->indent1st)    match = match+1;
  227.         if (sp->indent2nd ==    rp->indent2nd)    match = match+2;
  228.         if (sp->lineHt ==        rp->lineHt)    match = match+1;
  229.         if (sp->numTabs ==        rp->numTabs)    match = match+1;
  230.         if (sp->alignment ==    rp->alignment)    match = match+3;
  231.         if (scan->font ==        run->font)    match = match+10;
  232.         if (match>bestMatch) {
  233.             best=scan;
  234.             bestMatch=match;
  235.         }
  236.     }
  237.     }
  238.     if (TRACE) fprintf(stderr, "HTStyleForRun: Best match for style is %d out of 18\n",
  239.                  bestMatch);
  240.     return best;
  241. }
  242. #endif
  243.  
  244.  
  245. /*    Add a style to a sheet
  246. **    ----------------------
  247. */
  248. HTStyleSheet * HTStyleSheetAddStyle ARGS2
  249.   (HTStyleSheet *,self, HTStyle *,style)
  250. {
  251.     style->next = 0;        /* The style will go on the end */
  252.     if (!self->styles) {
  253.         self->styles = style;
  254.     } else {
  255.         HTStyle * scan;
  256.         for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
  257.     scan->next=style;
  258.     }
  259.     return self;
  260. }
  261.  
  262.  
  263. /*    Remove the given object from a style sheet if it exists
  264. */
  265. HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
  266.   (HTStyleSheet *,self, HTStyle *,style)
  267. {
  268.     if (self->styles = style) {
  269.         self->styles = style->next;
  270.     return self;
  271.     } else {
  272.         HTStyle * scan;
  273.     for(scan = self->styles; scan; scan = scan->next) {
  274.         if (scan->next = style) {
  275.             scan->next = style->next;
  276.         return self;
  277.         }
  278.     }
  279.     }
  280.     return 0;
  281. }
  282.  
  283. /*    Create new style sheet
  284. */
  285.  
  286. HTStyleSheet * HTStyleSheetNew NOARGS
  287. {
  288.     HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
  289.  
  290.     memset((void*)self, 0, sizeof(*self));    /* ANSI */
  291. /* Harbison c ref man says (char*)self
  292.    but k&r ansii and abc books and Think_C say (void*) */
  293.     
  294. /*    bzero(self, sizeof(*self)); */        /* BSD */
  295.     return self;
  296. }
  297.  
  298.  
  299. /*    Free off a style sheet pointer
  300. */
  301. HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
  302. {
  303.     HTStyle * style;
  304.     while((style=self->styles)!=0) {
  305.         self->styles = style->next;
  306.     HTStyleFree(style);
  307.     }
  308.     free(self);
  309.     return 0;
  310. }
  311.  
  312.  
  313. /*    Read a stylesheet from a typed stream
  314. **    -------------------------------------
  315. **
  316. **    Reads a style sheet from a stream.  If new styles have the same names
  317. **    as existing styles, they replace the old ones without changing the ids.
  318. */
  319.  
  320. #ifdef NEXT_SUPRESS  /* Only on the NeXT */
  321. HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
  322. {
  323.     int numStyles;
  324.     int i;
  325.     HTStyle * style;
  326.     char styleName[80];
  327.     NXScanf(stream, " %d ", &numStyles);
  328.     if (TRACE) fprintf(stderr, "Stylesheet: Reading %d styles\n", numStyles);
  329.     for (i=0; i<numStyles; i++) {
  330.         NXScanf(stream, "%s", styleName);
  331.         style = HTStyleNamed(self, styleName);
  332.     if (!style) {
  333.         style = HTStyleNewNamed(styleName);
  334.         (void) HTStyleSheetAddStyle(self, style);
  335.     }
  336.     (void) HTStyleRead(style, stream);
  337.     if (TRACE) HTStyleDump(style);
  338.     }
  339.     return self;
  340. }
  341.  
  342. /*    Write a stylesheet to a typed stream
  343. **    ------------------------------------
  344. **
  345. **    Writes a style sheet to a stream.
  346. */
  347.  
  348. HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
  349. {
  350.     int numStyles = 0;
  351.     HTStyle * style;
  352.     
  353.     for(style=self->styles; style; style=style->next) numStyles++;
  354.     NXPrintf(stream, "%d\n", numStyles);
  355.     
  356.     if (TRACE) fprintf(stderr, "StyleSheet: Writing %d styles\n", numStyles);
  357.     for (style=self->styles; style; style=style->next) {
  358.         NXPrintf(stream, "%s ", style->name);
  359.     (void) HTStyleWrite(style, stream);
  360.     }
  361.     return self;
  362. }
  363. #endif
  364.